package com.ruoyi.basedata.service.impl;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.basedata.domain.ElectricityAreaLine;
import com.ruoyi.basedata.domain.MeterSheets;
import com.ruoyi.basedata.domain.vo.EnergyExcelVo;
import com.ruoyi.basedata.domain.vo.CommonColumnVo;
import com.ruoyi.basedata.service.IMeterSheetsService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.basedata.mapper.ElectricityAreaLineMapper;
import com.ruoyi.basedata.service.IElectricityAreaLineService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

/**
 * 区域线损报表Service业务层处理
 *
 * @author zt
 * @date 2025-03-12
 */
@Service
public class ElectricityAreaLineServiceImpl extends ServiceImpl<ElectricityAreaLineMapper, ElectricityAreaLine> implements IElectricityAreaLineService
{
    @Autowired
    private ElectricityAreaLineMapper electricityAreaLineMapper;

    @Autowired
    private IMeterSheetsService meterSheetsService;

    /**
     * 查询区域线损报表
     *
     * @param id 区域线损报表主键
     * @return 区域线损报表
     */
    @Override
    public ElectricityAreaLine selectElectricityAreaLineById(Long id)
    {

        return electricityAreaLineMapper.selectById(id);
    }

    /**
     * 查询区域线损报表列表
     *
     * @param electricityAreaLine 区域线损报表
     * @return 区域线损报表
     */
    @Override
    public List<ElectricityAreaLine> selectElectricityAreaLineList(ElectricityAreaLine electricityAreaLine)
    {
        LambdaQueryWrapper<ElectricityAreaLine> queryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isEmpty(electricityAreaLine.getTenantId())){
            queryWrapper.eq(ElectricityAreaLine::getTenantId,electricityAreaLine.getTenantId());
        }
        if(electricityAreaLine.getAreaId() != null){
            queryWrapper.eq(ElectricityAreaLine::getAreaId,electricityAreaLine.getAreaId());
        }
        if(StringUtils.isEmpty(electricityAreaLine.getEnergyUseClassification())){
            queryWrapper.eq(ElectricityAreaLine::getEnergyUseClassification,electricityAreaLine.getEnergyUseClassification());
        }
        if(electricityAreaLine.getEnterPower() != null){
            queryWrapper.eq(ElectricityAreaLine::getEnterPower,electricityAreaLine.getEnterPower());
        }
        if(electricityAreaLine.getOutputPower() != null){
            queryWrapper.eq(ElectricityAreaLine::getOutputPower,electricityAreaLine.getOutputPower());
        }
        if(electricityAreaLine.getLineLoss() != null){
            queryWrapper.eq(ElectricityAreaLine::getLineLoss,electricityAreaLine.getLineLoss());
        }
        if(electricityAreaLine.getLineLossRate() != null){
            queryWrapper.eq(ElectricityAreaLine::getLineLossRate,electricityAreaLine.getLineLossRate());
        }
        if(electricityAreaLine.getEnterPowerHb() != null){
            queryWrapper.eq(ElectricityAreaLine::getEnterPowerHb,electricityAreaLine.getEnterPowerHb());
        }
        if(electricityAreaLine.getLineLossRateHb() != null){
            queryWrapper.eq(ElectricityAreaLine::getLineLossRateHb,electricityAreaLine.getLineLossRateHb());
        }
        if(electricityAreaLine.getOutputPowerHb() != null){
            queryWrapper.eq(ElectricityAreaLine::getOutputPowerHb,electricityAreaLine.getOutputPowerHb());
        }
        if(electricityAreaLine.getLineLossHb() != null){
            queryWrapper.eq(ElectricityAreaLine::getLineLossHb,electricityAreaLine.getLineLossHb());
        }
        if(StringUtils.isEmpty(electricityAreaLine.getFrozenType())){
            queryWrapper.eq(ElectricityAreaLine::getFrozenType,electricityAreaLine.getFrozenType());
        }
        if(StringUtils.isEmpty(electricityAreaLine.getFreezeTime())){
            queryWrapper.eq(ElectricityAreaLine::getFreezeTime,electricityAreaLine.getFreezeTime());
        }
        if(StringUtils.isEmpty(electricityAreaLine.getCreator())){
            queryWrapper.eq(ElectricityAreaLine::getCreator,electricityAreaLine.getCreator());
        }
        if(StringUtils.isEmpty(electricityAreaLine.getUpdater())){
            queryWrapper.eq(ElectricityAreaLine::getUpdater,electricityAreaLine.getUpdater());
        }
        return electricityAreaLineMapper.selectList(queryWrapper);
    }

    /**
     * 新增区域线损报表
     *
     * @param electricityAreaLine 区域线损报表
     * @return 结果
     */
    @Override
    public int insertElectricityAreaLine(ElectricityAreaLine electricityAreaLine)
    {
        return electricityAreaLineMapper.insert(electricityAreaLine);
    }


    /**
     * 能耗线损报表
     * @param frozen_type
     * @param freezeTime
     * @return
     */
    @Override
    public int insertElectricityAreaLineForAll(String frozen_type, String freezeTime)
    {
        if("day".equals(frozen_type)){
            return electricityAreaLineMapper.insertByDay(freezeTime);
        }else if("month".equals(frozen_type)){
            return electricityAreaLineMapper.insertByMonth(freezeTime);
        }
        return 0;
    }
    /**
     * 修改区域线损报表
     *
     * @param electricityAreaLine 区域线损报表
     * @return 结果
     */
    @Override
    public int updateElectricityAreaLine(ElectricityAreaLine electricityAreaLine)
    {
        electricityAreaLine.setUpdateTime(DateUtils.getNowDate());
        return electricityAreaLineMapper.updateById(electricityAreaLine);
    }

    /**
     * 批量删除区域线损报表
     *
     * @param ids 需要删除的区域线损报表主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteElectricityAreaLineByIds(Long[] ids)
    {
        return electricityAreaLineMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除区域线损报表信息
     *
     * @param id 区域线损报表主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteElectricityAreaLineById(Long id)
    {
        return electricityAreaLineMapper.deleteById(id);
    }

    /**
    * @Description: 获取线损报表
    * @date: 2025/3/12 10:48
    * @author: zt
    */
    @Override
    public Map<String, Object> getLineLossReportList(ElectricityAreaLine electricityAreaLine) {
        if(electricityAreaLine == null){
            return null;
        }
        Map<String,Object> resultMap = new HashMap<>();
        //生成列属性
        //{key: 0, label: `名称`, visible: true, width:150, prop: 'areaName', fixed: 'left'},
        List<CommonColumnVo> columns = new ArrayList<>();
        columns.add(CommonColumnVo.builder().key(0).label("名称").visible(true).width(200).prop("areaName").fixed("left").build());
        columns.add(CommonColumnVo.builder().key(1).label("日期").visible(true).width(120).prop("freezeTime").build());
        String frozenType = electricityAreaLine.getFrozenType();//冻结类型
        String freezeTime = electricityAreaLine.getFreezeTime();//时间
        if ("hour".equals(frozenType)) {
            freezeTime = freezeTime.substring(0,10);
            for (int i = 0; i < 24; i++) {
                columns.add(getColumn(i<10? "0"+i : ""+i,2+i,i+1));
            }
        }else if ("day".equals(frozenType)) {
            freezeTime = freezeTime.substring(0, 7);
            int days = DateUtil.getLastDayOfMonth(DateUtil.parse(freezeTime,"yyyy-MM"));
            for (int i = 1; i <= days; i++) {
                columns.add(getColumn(i<10? "0"+i : ""+i,2+i,i));
            }
        }else if ("month".equals(frozenType)) {
            freezeTime = freezeTime.substring(0,4);
            for (int i = 1; i <= 12; i++) {
                columns.add(getColumn(i<10? "0"+i : ""+i,2+i,i));
            }
        }
        resultMap.put("columns",columns);
//        SysUser user = SecurityUtils.getLoginUser().getUser();
        //生成数据
        //1.查询条件
        LambdaQueryWrapper<ElectricityAreaLine> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ElectricityAreaLine::getFrozenType,frozenType);
//        if (user.getSystemFlag() != Constants.SYS_FLAG_ADMIN){
//            wrapper.eq(ElectricityAreaLine::getTenantId,user.getTenantId());
//        }
        //区域
        if(!electricityAreaLine.getAreaIds().isEmpty()) {
            wrapper.in(ElectricityAreaLine::getAreaId, electricityAreaLine.getAreaIds());
        }
        //能耗分类
        wrapper.eq(ElectricityAreaLine::getEnergyUseClassification,electricityAreaLine.getEnergyUseClassification());
        
        //时间
        if("hour".equals(frozenType)){
            wrapper.ge(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,10)+" 00:00:00");
            wrapper.le(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,10)+" 23:59:59");
        } else if ("day".equals(frozenType)) {
            String month = freezeTime.substring(0, 7);
            int days =DateUtil.getLastDayOfMonth(DateUtil.parse(month,"yyyy-MM"));
//            wrapper.ge(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,7)+"-01 00:00:00");
//            wrapper.le(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,7)+"-"+days+" 23:59:59");
            wrapper.ge(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,7)+"-01");
            wrapper.le(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,7)+"-"+days);
        }else {
//            wrapper.ge(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,4)+"-01-01 00:00:00");
//            wrapper.le(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,4)+"-12-31 23:59:59");
            wrapper.ge(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,4)+"-01");
            wrapper.le(ElectricityAreaLine::getFreezeTime,freezeTime.substring(0,4)+"-12");
        }
        List<ElectricityAreaLine> list = electricityAreaLineMapper.selectList(wrapper);
        if(!list.isEmpty()){
            //根据区域ID分组
            Map<Long,List<ElectricityAreaLine>> areaDataMap = list.stream().collect(Collectors.groupingBy(ElectricityAreaLine::getAreaId));

            //2.查询区域信息
            //{key: 0, label: `名称`, visible: true, width:150, prop: 'areaName', fixed: 'left'},
            List<MeterSheets> sheetsList = meterSheetsService.getAreaTree(1,null,null,null,null,false);
            List<MeterSheets> newList = recursive(sheetsList,electricityAreaLine.getAreaIds());
            resultMap.put("data",recursiveData(freezeTime,newList,areaDataMap,columns));
        }
        return resultMap;
    }

    private CommonColumnVo getColumn(String label,int key,int i){
        List<CommonColumnVo> childColumns = new ArrayList<>();
        childColumns.add(CommonColumnVo.builder().key(key).label("输入量").visible(true).prop("key_in"+i).build());
        childColumns.add(CommonColumnVo.builder().key(key).label("输出量").visible(true).prop("key_out"+i).build());
        childColumns.add(CommonColumnVo.builder().key(key).label("线损量").visible(true).prop("key_loss"+i).build());
        CommonColumnVo columnVo = CommonColumnVo.builder().label(label).build();
        columnVo.setChildren(childColumns);
        return columnVo;
    }

    @Override
    public void exportElectricityAreaLineList(HttpServletResponse response, ElectricityAreaLine electricityAreaLine) throws IOException {
        Map<String, Object> dataMap = getLineLossReportList(electricityAreaLine);
        List<Map<String,Object>> dataList = new ArrayList<>();
        if(dataMap.containsKey("data")){
            List<Map<String,Object>> list = (List<Map<String, Object>>) dataMap.get("data");
            dataList = recursiveExportData(list);
        }
        List<CommonColumnVo> columns = JSONArray.parseArray(JSON.toJSONString(dataMap.get("columns")), CommonColumnVo.class) ;
        export(response,"区域线损报表数据",dataList,columns);
    }

    private void export(HttpServletResponse response, String fileName, List<?> projects, List<CommonColumnVo> columns) throws IOException {
        ExcelWriter bigWriter = cn.hutool.poi.excel.ExcelUtil.getBigWriter();
        //创建一行空表头占个位置
        bigWriter.writeHeadRow(new LinkedList<>());
        //创建需要展示的的二级表头，{filedName,中文名}
        int lastCol = 0;
        for (int i = 0; i < columns.size(); i++) {
            if (columns.get(i).getChildren() != null) {
                for (int j = 0; j < columns.get(i).getChildren().size(); j++) {
                    bigWriter.addHeaderAlias(columns.get(i).getChildren().get(j).getProp(), columns.get(i).getChildren().get(j).getLabel());
                    bigWriter.setColumnWidth(lastCol++, 30);
                }
            }else {
                bigWriter.addHeaderAlias(columns.get(i).getProp(), columns.get(i).getLabel());
                bigWriter.setColumnWidth(lastCol++, 30);
            }
        }
        //根据需要合并添加第一列表头
        bigWriter.merge(0, 1, 0, 0, columns.get(0).getLabel(), true);
        bigWriter.merge(0, 1, 1, 1, columns.get(1).getLabel(), true);
        for (int i = 2; i < columns.size(); i++) {
            if (columns.get(i).getChildren() != null) {
                bigWriter.merge(0, 0, 3*i-4, 3*i-2, columns.get(i).getLabel(), true);
            }
        }
        bigWriter.setOnlyAlias(true);
        bigWriter.write(projects, true);
        StyleSet styleSet = bigWriter.getStyleSet();
        styleSet.setWrapText();
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("filename", URLEncoder.encode(fileName+".xlsx","UTF-8"));
        ServletOutputStream out = response.getOutputStream();
        bigWriter.flush(out, true);
        bigWriter.close();
        IoUtil.close(out);
    }

    public List<Map<String,Object>> recursiveExportData(List<Map<String,Object>> list){
        List<Map<String,Object>> dataList = new ArrayList<>();
        for (Map<String,Object> excelVo : list) {
            dataList.add(excelVo);
            if(excelVo.containsKey("children")){
                List<Map<String,Object>> tt = (List<Map<String, Object>>) excelVo.get("children");
                if(!tt.isEmpty()){
                    dataList.addAll(recursiveExportData(tt));
                }
            }
        }
        return dataList;
    }

    //递归数据
    public List<Map<String,Object>> recursiveData(String freezeTime,List<MeterSheets> sheetsList,Map<Long,List<ElectricityAreaLine>> areaDataMap,List<CommonColumnVo> columns){
        List<Map<String,Object>> resList = new ArrayList<>();
        for (MeterSheets meterSheets : sheetsList) {
            Map<String,Object> map = new HashMap<>();
            Long areaId = meterSheets.getId();
            List<ElectricityAreaLine> reportList = areaDataMap.get(areaId);
            //返回日期map
//            Map<String,ElectricityAreaLine> reportMap = (reportList == null || reportList.isEmpty()) ? null : reportList.stream().collect(Collectors.toMap(ElectricityAreaLine::getFreezeTime, Function.identity()));
            Map<String,List<ElectricityAreaLine>> reportMap = (reportList == null || reportList.isEmpty()) ? null : reportList.stream().collect(Collectors.groupingBy(ElectricityAreaLine::getFreezeTime));
            //列{key: 0, label: `名称`, visible: true, width:150, prop: 'areaName', fixed: 'left'}
            map.put("areaId",areaId);
            for (CommonColumnVo vo : columns) {
                if(!StringUtils.isEmpty(vo.getProp()) && "areaName".equals(vo.getProp())){
                    map.put(vo.getProp(),meterSheets.getSheetsName());
                }else if(!StringUtils.isEmpty(vo.getProp()) && "freezeTime".equals(vo.getProp())){
                    map.put(vo.getProp(),freezeTime);
                }
                else if(StringUtils.isEmpty(vo.getProp()) && vo.getChildren()!=null && !vo.getChildren().isEmpty()){
                    List<CommonColumnVo> cList = vo.getChildren();
                    //日期列字段，key_in1,key_out1,key_loss1,key_in2,key_out2,key_loss2...
                    String label = vo.getLabel();
                    String ftime = freezeTime + " " + label + ":00:00";
                    if(freezeTime.length() == 10){//时
                        ftime = freezeTime + " " + label + ":00:00";
                    }else {//日,月
                        ftime = freezeTime + "-" + label;
                    }
                    ElectricityAreaLine temp = null;
                    if(reportMap!=null && reportMap.containsKey(ftime)){
                        temp = reportMap.get(ftime).get(0);
                    }
                    if(temp == null){
                        map.put(cList.get(0).getProp(),"");
                        map.put(cList.get(1).getProp(),"");
                        map.put(cList.get(2).getProp(),"");
                    }else {
                        map.put(cList.get(0).getProp(),temp.getEnterPower() == null ? "" : temp.getEnterPower());
                        map.put(cList.get(1).getProp(),temp.getOutputPower() == null ? "" : temp.getOutputPower());
                        map.put(cList.get(2).getProp(),temp.getLineLoss() == null ? "" : temp.getLineLoss());
                    }
                }
            }
            if(!meterSheets.getChildren().isEmpty()){
                map.put("children",recursiveData(freezeTime,meterSheets.getChildren(),areaDataMap,columns));
            }
            resList.add(map);
        }
        return resList;
    }

    //递归-过滤选择的区域
    public List<MeterSheets> recursive(List<MeterSheets> sheetsList,List<Long> areaIds){
        Iterator<MeterSheets> iterator = sheetsList.iterator();
        while (iterator.hasNext()) {
            MeterSheets sheet = iterator.next();
            Long areaId = sheet.getId();
            //包含该区域
            if(areaIds.contains(areaId)){
                sheet.setChildren(recursive(sheet.getChildren(),areaIds));
            }else {
                iterator.remove();
            }
        }
        return sheetsList;
    }
}
